-
Notifications
You must be signed in to change notification settings - Fork 559
[Dashboard] Add chain infrastructure deployment and management #7456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
|
WalkthroughThis update introduces a new blockchain infrastructure deployment feature, including multi-step UI flows for selecting chains and services, dynamic pricing, and checkout integration. It adds new API utilities for ecosystem and chain subscription management, restructures type imports for consistency, and removes obsolete local data-fetching helpers. Sidebar navigation is enhanced to surface chain infrastructure subscriptions per team. Changes
Sequence Diagram(s)Infrastructure Deployment FlowsequenceDiagram
participant User
participant DeployInfrastructurePage (Step 1)
participant SingleNetworkSelector
participant DeployInfrastructureOnChainPage (Step 2)
participant DeployInfrastructureForm
participant BillingAPI
User->>DeployInfrastructurePage: Visit /team/[team_slug]/~/infrastructure/deploy
DeployInfrastructurePage->>SingleNetworkSelector: Render chain selector
User->>SingleNetworkSelector: Select chain
DeployInfrastructurePage->>User: Enable "Continue" button
User->>DeployInfrastructurePage: Click "Continue"
DeployInfrastructurePage->>DeployInfrastructureOnChainPage: Navigate to /deploy/[chain_id]
DeployInfrastructureOnChainPage->>DeployInfrastructureForm: Render service selection form
User->>DeployInfrastructureForm: Select services, billing frequency
User->>DeployInfrastructureForm: Click "Checkout"
DeployInfrastructureForm->>BillingAPI: Call getChainInfraCheckoutURL
BillingAPI-->>DeployInfrastructureForm: Return checkout URL or error
DeployInfrastructureForm->>User: Open checkout or show error
Sidebar Chain Infrastructure LinkssequenceDiagram
participant TeamLayout
participant API
participant TeamSidebarLayout
participant User
TeamLayout->>API: fetchEcosystemList, getChainSubscriptions
API-->>TeamLayout: Ecosystem list, chain subscriptions
TeamLayout->>TeamSidebarLayout: Pass chainSubscriptions prop
TeamSidebarLayout->>User: Render sidebar with dynamic "Chain Infrastructure" submenu
Ecosystem Fetch RefactorsequenceDiagram
participant EcosystemPage
participant fetchEcosystem (API)
participant API Server
EcosystemPage->>fetchEcosystem: Call with slug, team_slug
fetchEcosystem->>API Server: GET /api/teams/{team_slug}/ecosystems/{slug}
API Server-->>fetchEcosystem: Ecosystem data or error
fetchEcosystem-->>EcosystemPage: Ecosystem data or null
Suggested reviewers
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
size-limit report 📦
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (6)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx (1)
1-3
: Consider enhancing the infrastructure overview page.While this minimal implementation works as a placeholder, consider adding more meaningful content such as:
- Infrastructure service status overview
- Quick access links to deploy new services
- Summary of existing infrastructure
This would provide better user experience compared to the current basic text display.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx (2)
8-12
: Consider exposing className prop for better composability.Following the coding guidelines, components should expose a
className
prop when useful for styling flexibility.export function OrderSummary(props: { selectedChainId: number; selectedServices: ServiceConfig[]; paymentFrequency: PaymentFrequency; + className?: string; }) {
And apply it to the root div:
- <div className="space-y-4"> + <div className={cn("space-y-4", props.className)}>
93-93
: Consider making discount percentages configurable.The discount percentages (15% annual, 10-15% bundle) are hardcoded, which reduces flexibility for business logic changes.
Consider extracting these into configuration constants or props:
+const DISCOUNT_CONFIG = { + annual: 0.15, + bundle: { + twoServices: 0.1, + threeServices: 0.15, + }, +} as const; // Then use in calculations: - const annualDiscount = paymentFrequency === "annual" ? 0.15 : 0; + const annualDiscount = paymentFrequency === "annual" ? DISCOUNT_CONFIG.annual : 0;Also applies to: 162-166, 169-169
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (3)
22-26
: Consider exposing className prop for better composability.Following the coding guidelines, components should expose a
className
prop for styling flexibility.export function ServiceSelector(props: { services: ServiceConfig[]; selectedServices: ServiceConfig[]; setSelectedServices: (services: ServiceConfig[]) => void; + className?: string; }) {
113-116
: Break down complex className for better readability.The className string is very long and hard to read. Consider breaking it into multiple lines or extracting parts into variables.
<Label className={cn( - "hover:bg-accent/50 flex gap-6 rounded-lg border px-6 py-4 has-[[aria-checked=true]]:border-primary has-[[aria-checked=true]]:bg-primary/10 cursor-pointer items-center", + "flex items-center gap-6 rounded-lg border px-6 py-4 cursor-pointer", + "hover:bg-accent/50", + "has-[[aria-checked=true]]:border-primary has-[[aria-checked=true]]:bg-primary/10", props.service.required && "cursor-not-allowed", )} >
146-153
: Consider responsive design for feature list.The features are completely hidden on mobile (
hidden lg:grid
). Consider showing a subset or using a different layout for better mobile experience.- <div className="grid-cols-2 gap-2 hidden lg:grid"> + <div className="grid grid-cols-1 lg:grid-cols-2 gap-2"> {props.service.features.map((feature) => ( <div className="flex items-center space-x-1 text-sm" key={feature}> <CheckIcon className="w-3 h-3 shrink-0 text-success-text" /> <span>{feature}</span> </div> ))} </div>Or limit features shown on mobile:
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-2"> + {props.service.features.slice(0, 2).map((feature) => ( + <div className="flex items-center space-x-1 text-sm" key={feature}> + <CheckIcon className="w-3 h-3 shrink-0 text-success-text" /> + <span>{feature}</span> + </div> + ))} + {props.service.features.length > 2 && ( + <div className="text-sm text-muted-foreground lg:hidden"> + +{props.service.features.length - 2} more features + </div> + )} + </div>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
apps/dashboard/biome.json
(1 hunks)apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx
(2 hunks)apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx
(2 hunks)apps/dashboard/src/@/icons/ChainIcon.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx
(1 hunks)apps/nebula/biome.json
(1 hunks)apps/playground-web/biome.json
(1 hunks)apps/portal/biome.json
(1 hunks)apps/wallet-ui/biome.json
(1 hunks)biome.json
(1 hunks)packages/engine/biome.json
(1 hunks)packages/insight/biome.json
(1 hunks)packages/nebula/biome.json
(1 hunks)packages/react-native-adapter/biome.json
(1 hunks)packages/service-utils/biome.json
(1 hunks)packages/thirdweb/biome.json
(1 hunks)packages/vault-sdk/biome.json
(1 hunks)packages/wagmi-adapter/biome.json
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
`apps/dashboard/*`: The dashboard app is a web-based developer console built wit...
apps/dashboard/*
: The dashboard app is a web-based developer console built with Next.js and Chakra UI.
Use Tailwind CSS only for styling; no inline styles or CSS modules.
Use cn() from @/lib/utils for conditional class merging.
Use design system tokens for backgrounds (bg-card), borders (border-border), and muted text (text-muted-foreground).
Expose className prop on the root element of components for overrides.
Use NavLink for internal navigation with automatic active states.
Server components should start files with import "server-only"; client components should begin files with 'use client';.
Never import posthog-js in server components; analytics events are client-side only.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
apps/dashboard/biome.json
`packages/thirdweb/*`: Every public symbol in the SDK must have comprehensive TS...
packages/thirdweb/*
: Every public symbol in the SDK must have comprehensive TSDoc with at least one @example block that compiles and custom annotation tags (@beta, @internal, @experimental).
Export everything via the exports/ directory, grouped by feature.
Place tests alongside code: foo.ts ↔ foo.test.ts.
Use real function invocations with stub data in tests; avoid brittle mocks.
Use Mock Service Worker (MSW) for fetch/HTTP call interception in tests.
Keep tests deterministic and side-effect free.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
packages/thirdweb/biome.json
`apps/wallet-ui/*`: The wallet-ui app is for wallet interface and testing.
apps/wallet-ui/*
: The wallet-ui app is for wallet interface and testing.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
apps/wallet-ui/biome.json
`biome.json`: Biome is the primary linter/formatter; rules are defined in biome.json.
biome.json
: Biome is the primary linter/formatter; rules are defined in biome.json.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
biome.json
`packages/wagmi-adapter/*`: Wagmi ecosystem integration is located in packages/wagmi-adapter/.
packages/wagmi-adapter/*
: Wagmi ecosystem integration is located in packages/wagmi-adapter/.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
packages/wagmi-adapter/biome.json
`apps/portal/*`: The portal app is a documentation site with MDX.
apps/portal/*
: The portal app is a documentation site with MDX.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
apps/portal/biome.json
`packages/react-native-adapter/*`: Mobile platform shims are located in packages/react-native-adapter/.
packages/react-native-adapter/*
: Mobile platform shims are located in packages/react-native-adapter/.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
packages/react-native-adapter/biome.json
`**/icons/*`: Icons come from 'lucide-react' or the project-specific '../icons' exports – never embed raw SVG.
**/icons/*
: Icons come from 'lucide-react' or the project-specific '../icons' exports – never embed raw SVG.
📄 Source: CodeRabbit Inference Engine (.cursor/rules/dashboard.mdc)
List of files the instruction was applied to:
apps/dashboard/src/@/icons/ChainIcon.tsx
`**/*.@(ts|tsx)`: Accept a typed 'props' object and export a named function (e.g...
**/*.@(ts|tsx)
: Accept a typed 'props' object and export a named function (e.g., export function MyComponent()).
Combine class names via 'cn', expose 'className' prop if useful.
Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Local state or effects live inside; data fetching happens in hooks.
Merge class names with 'cn' from '@/lib/utils' to keep conditional logic readable.
Stick to design-tokens: background ('bg-card'), borders ('border-border'), muted text ('text-muted-foreground') etc.
Use the 'container' class with a 'max-w-7xl' cap for page width consistency.
Spacing utilities ('px-', 'py-', 'gap-*') are preferred over custom margins.
Responsive helpers follow mobile-first ('max-sm', 'md', 'lg', 'xl').
Never hard-code colors – always go through Tailwind variables.
Tailwind CSS is the styling system – avoid inline styles or CSS modules.
Prefix files with 'import "server-only";' so they never end up in the client bundle (for server-only code).
📄 Source: CodeRabbit Inference Engine (.cursor/rules/dashboard.mdc)
List of files the instruction was applied to:
apps/dashboard/src/@/icons/ChainIcon.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx
apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx
apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx
`apps/nebula/*`: The nebula app is for account abstraction and smart wallet management.
apps/nebula/*
: The nebula app is for account abstraction and smart wallet management.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
apps/nebula/biome.json
`apps/playground-web/*`: The playground-web app is an interactive SDK testing environment.
apps/playground-web/*
: The playground-web app is an interactive SDK testing environment.
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
apps/playground-web/biome.json
🧠 Learnings (13)
📓 Common learnings
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
apps/dashboard/src/@/icons/ChainIcon.tsx (2)
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: MananTank
PR: thirdweb-dev/js#7177
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractHeader.tsx:26-43
Timestamp: 2025-05-29T10:49:52.981Z
Learning: In React image components, conditional rendering of the entire image container (e.g., `{props.image && <Img />}`) serves a different purpose than fallback handling. The conditional prevents rendering any image UI when no image metadata exists, while the fallback prop handles cases where image metadata exists but the image fails to load. This pattern is intentional to distinguish between "no image intended" vs "image intended but failed to load".
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx (13)
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: UI primitives should be imported from @/components/ui/*.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Always import reusable UI components from a central library (e.g., '@/components/ui/*') to ensure consistency and avoid duplication.
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Client components must begin with 'use client'; before imports to ensure correct rendering behavior in Next.js.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Prefer composable UI primitives (Button, Input, Select, Tabs, Card, Sidebar, Separator, Badge) over custom markup for maintainability and design consistency.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: Client components should begin files with 'use client' and use React hooks for interactivity.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Use client components for interactive UI, components that rely on hooks, browser APIs, or require fast transitions.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Reuse core UI primitives and avoid re-implementing common elements like buttons, cards, or modals.
Learnt from: MananTank
PR: thirdweb-dev/js#7356
File: apps/nebula/src/app/not-found.tsx:1-1
Timestamp: 2025-06-17T18:30:52.976Z
Learning: In the thirdweb/js project, the React namespace is available for type annotations (like React.FC) without needing to explicitly import React. This is project-specific configuration that differs from typical TypeScript/React setups.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/page.tsx:20-20
Timestamp: 2025-05-26T16:26:58.068Z
Learning: In team/project contract pages under routes like `/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/*`, users are always logged in by design. The hardcoded `isLoggedIn={true}` prop in these pages is intentional and correct, not a bug to be fixed.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx (5)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: jnsdls
PR: thirdweb-dev/js#7363
File: apps/dashboard/src/app/(app)/layout.tsx:63-74
Timestamp: 2025-06-18T02:01:06.006Z
Learning: In Next.js applications, instrumentation files (instrumentation.ts or instrumentation-client.ts) placed in the src/ directory are automatically handled by the framework and included in the client/server bundles without requiring manual imports. The framework injects these files as part of the build process.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx (2)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: MananTank
PR: thirdweb-dev/js#7298
File: apps/dashboard/src/app/nebula-app/move-funds/move-funds.tsx:424-424
Timestamp: 2025-06-06T23:46:08.795Z
Learning: The thirdweb project has an ESLint rule that restricts direct usage of `defineChain`. When it's necessary to use `defineChain` directly, it's acceptable to disable the rule with `// eslint-disable-next-line no-restricted-syntax`.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx (7)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/page.tsx:2-10
Timestamp: 2025-05-26T16:28:10.079Z
Learning: In Next.js 14+, the `params` object in page components is always a Promise that needs to be awaited, so the correct typing is `params: Promise<ParamsType>` rather than `params: ParamsType`.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/page.tsx:20-20
Timestamp: 2025-05-26T16:26:58.068Z
Learning: In team/project contract pages under routes like `/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/*`, users are always logged in by design. The hardcoded `isLoggedIn={true}` prop in these pages is intentional and correct, not a bug to be fixed.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/shared-page.tsx:41-48
Timestamp: 2025-05-26T16:28:50.772Z
Learning: The `projectMeta` prop is not required for the server-rendered `ContractTokensPage` component in the tokens shared page, unlike some other shared pages where it's needed for consistency.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx (3)
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Prefer composable UI primitives (Button, Input, Select, Tabs, Card, Sidebar, Separator, Badge) over custom markup for maintainability and design consistency.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx (9)
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: Client components should begin files with 'use client' and use React hooks for interactivity.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: jnsdls
PR: thirdweb-dev/js#7364
File: apps/dashboard/src/app/(app)/account/components/AccountHeader.tsx:36-41
Timestamp: 2025-06-18T02:13:34.500Z
Learning: In the logout flow in apps/dashboard/src/app/(app)/account/components/AccountHeader.tsx, when `doLogout()` fails, the cleanup steps (resetAnalytics(), wallet disconnect, router refresh) should NOT execute. This is intentional to maintain consistency - if server-side logout fails, client-side cleanup should not occur.
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx (12)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: jnsdls
PR: thirdweb-dev/js#7363
File: apps/dashboard/src/app/(app)/layout.tsx:63-74
Timestamp: 2025-06-18T02:01:06.006Z
Learning: In Next.js applications, instrumentation files (instrumentation.ts or instrumentation-client.ts) placed in the src/ directory are automatically handled by the framework and included in the client/server bundles without requiring manual imports. The framework injects these files as part of the build process.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/direct-listings/shared-direct-listings-page.tsx:47-52
Timestamp: 2025-05-26T16:29:54.317Z
Learning: The `projectMeta` prop is not required for the server-rendered `ContractDirectListingsPage` component in the direct listings shared page, following the same pattern as other server components in the codebase where `projectMeta` is only needed for client components.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/shared-page.tsx:41-48
Timestamp: 2025-05-26T16:28:50.772Z
Learning: The `projectMeta` prop is not required for the server-rendered `ContractTokensPage` component in the tokens shared page, unlike some other shared pages where it's needed for consistency.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Client components must begin with 'use client'; before imports to ensure correct rendering behavior in Next.js.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: Client components should begin files with 'use client' and use React hooks for interactivity.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/analytics/shared-analytics-page.tsx:33-39
Timestamp: 2025-05-26T16:30:24.965Z
Learning: In the thirdweb dashboard codebase, redirectToContractLandingPage function already handles execution termination internally (likely using Next.js redirect() which throws an exception), so no explicit return statement is needed after calling it.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/shared-claim-conditions-page.tsx:43-49
Timestamp: 2025-05-26T16:31:02.480Z
Learning: In the thirdweb dashboard codebase, when `redirectToContractLandingPage()` is called, an explicit return statement is not required afterward because the function internally calls Next.js's `redirect()` which throws an error to halt execution.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx (8)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/page.tsx:2-10
Timestamp: 2025-05-26T16:28:10.079Z
Learning: In Next.js 14+, the `params` object in page components is always a Promise that needs to be awaited, so the correct typing is `params: Promise<ParamsType>` rather than `params: ParamsType`.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/page.tsx:20-20
Timestamp: 2025-05-26T16:26:58.068Z
Learning: In team/project contract pages under routes like `/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/*`, users are always logged in by design. The hardcoded `isLoggedIn={true}` prop in these pages is intentional and correct, not a bug to be fixed.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Client components must begin with 'use client'; before imports to ensure correct rendering behavior in Next.js.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx (2)
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (5)
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: Group feature-specific components under feature/components/* with a barrel index.ts.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Prefer composable UI primitives (Button, Input, Select, Tabs, Card, Sidebar, Separator, Badge) over custom markup for maintainability and design consistency.
apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx (5)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: jnsdls
PR: thirdweb-dev/js#7365
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx:16-17
Timestamp: 2025-06-18T04:30:04.326Z
Learning: Next.js Link component fully supports both internal and external URLs and works appropriately with all standard anchor attributes including target="_blank", rel="noopener noreferrer", etc. Using Link for external URLs is completely appropriate and recommended.
Learnt from: jnsdls
PR: thirdweb-dev/js#7365
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx:16-17
Timestamp: 2025-06-18T04:27:16.172Z
Learning: Next.js Link component supports external URLs without throwing errors. When used with absolute URLs (like https://...), it behaves like a regular anchor tag without client-side routing, but does not cause runtime crashes or errors as previously believed.
Learnt from: MananTank
PR: thirdweb-dev/js#7177
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractHeader.tsx:26-43
Timestamp: 2025-05-29T10:49:52.981Z
Learning: In React image components, conditional rendering of the entire image container (e.g., `{props.image && <Img />}`) serves a different purpose than fallback handling. The conditional prevents rendering any image UI when no image metadata exists, while the fallback prop handles cases where image metadata exists but the image fails to load. This pattern is intentional to distinguish between "no image intended" vs "image intended but failed to load".
🧬 Code Graph Analysis (3)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx (1)
InfrastructurePage
(3-12)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx (1)
apps/dashboard/src/@/components/ui/radio-group.tsx (1)
RadioGroupItemButton
(75-75)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx (2)
apps/dashboard/src/@/api/team.ts (1)
getTeamBySlug
(13-32)apps/dashboard/src/@/components/blocks/upsell-wrapper.tsx (1)
UpsellWrapper
(34-74)
⏰ Context from checks skipped due to timeout of 90000ms (8)
- GitHub Check: Size
- GitHub Check: Unit Tests
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Build Packages
- GitHub Check: Lint Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (27)
biome.json (1)
2-2
: Ensure the toolchain is upgraded to Biome 2.0.4+The schema bump is fine, but editors/CI will complain if the locally installed
@biomejs/biome
CLI is still on 2.0.0.
Please verify the rootpackage.json
(or each workspace) pins@biomejs/biome
≥ 2.0.4 before this lands.packages/insight/biome.json (1)
2-2
: Same schema bump as the root file; handled by the earlier comment. No further feedback.packages/service-utils/biome.json (1)
2-2
: Same schema bump as the root file; handled by the earlier comment. No further feedback.packages/nebula/biome.json (1)
2-2
: Same schema bump as the root file; handled by the earlier comment. No further feedback.packages/engine/biome.json (1)
2-2
: Same schema bump as the root file; handled by the earlier comment. No further feedback.apps/wallet-ui/biome.json (1)
2-2
: Verify Biome CLI/tooling is on ≥ 2.0.4 before mergingThe schema bump is harmless, but config validation will fail locally/CI if any environment is still pinned to 2.0.0. Double-check the version in
package.json
/ lockfiles or CI images.apps/portal/biome.json (1)
2-2
: Confirm portal build pipeline uses Biome 2.0.4Same note as other apps: ensure the CLI version matches the new schema to avoid lint/format errors in CI.
packages/thirdweb/biome.json (1)
2-2
: SDK package also needs Biome 2.0.4 in dev-depsUpdating the schema without bumping the dev dependency may break
pnpm lint
for package authors. Verify the root workspace has the correct version.apps/dashboard/biome.json (1)
2-2
: Dashboard app: check Docker/CI image for Biome version driftIf the dashboard is built inside a container, ensure the image was rebuilt with Biome 2.0.4; otherwise schema validation will complain.
apps/playground-web/biome.json (1)
2-2
: Playground-web: sync local VSCode extension + CI to Biome 2.0.4Developers’ editors and CI must understand the new schema; confirm extension/update is applied.
packages/vault-sdk/biome.json (1)
2-2
: Schema version bump looks goodThe config now references the 2.0.4 schema, matching the rest of the repo. No further action required as long as the CI environment is already running Biome ≥ 2.0.4.
packages/wagmi-adapter/biome.json (1)
2-2
: Consistent schema upgradeUpgrade to 2.0.4 keeps the wagmi-adapter package aligned with the global tooling.
packages/react-native-adapter/biome.json (1)
2-2
: LGTM – schema reference updatedNothing else changed; integration with the React-Native adapter remains unaffected.
apps/nebula/biome.json (1)
2-2
: Nebula biome.json updated correctlyThe schema URL now points to 2.0.4, in sync with other apps.
apps/dashboard/src/@/icons/ChainIcon.tsx (1)
33-33
: LGTM! Semantic improvement for skeleton placeholder.The change from
<div>
to<span>
is appropriate since spans are inline elements better suited for icon placeholders while maintaining the same styling and animation behavior.apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx (3)
155-155
: LGTM! Proper prop addition.The optional
disableDeprecated
prop is well-typed and follows the established pattern of other boolean filter props in this component.
173-175
: LGTM! Correct filtering implementation.The filtering logic properly excludes chains with deprecated status, using the standard filtering pattern consistent with other conditional filters in this component.
178-183
: LGTM! Proper dependency array update.The dependency array correctly includes
disableDeprecated
to ensure the memoizedchainsToShow
recalculates when the filter option changes.apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx (2)
9-9
: LGTM! Proper UI primitive import.Badge component correctly imported from the central UI library, following established coding guidelines.
90-97
: LGTM! Well-structured tab addition.The Infrastructure tab implementation follows the established pattern with proper JSX structure for the name prop containing the Badge component. The routing path is consistent with other team navigation tabs.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx (1)
4-8
: LGTM! Proper server component pattern.The implementation correctly follows the established server component pattern by initializing the client on the server side and passing it to the client component.
Verify team context handling.
Since this page is in the team route structure (
/team/[team_slug]/...
), ensure that theInfrastructureCheckout
component can access the necessary team context. If team information is required, consider extracting the team_slug from params.#!/bin/bash # Description: Check if InfrastructureCheckout component needs team context # Expected: Find usage of team context or team_slug in the checkout component ast-grep --pattern $'function InfrastructureCheckout($$$) { $$$ }' # Also check for any team-related props or usage rg -A 10 -B 5 "team" apps/dashboard/src/app/\(app\)/team/\[team_slug\]/\(team\)/~/infrastructure/deploy/_components/checkout.tsxapps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx (1)
3-12
: LGTM! Clean implementation following Next.js 14+ patterns.The component correctly awaits the params Promise and uses the existing
getChain
utility. The implementation is straightforward and follows the established patterns in the codebase.apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx (1)
8-46
: LGTM! Well-structured layout with proper access control.The component correctly:
- Awaits params following Next.js 14+ patterns
- Fetches team data and handles missing teams gracefully
- Implements proper billing plan access control via
UpsellWrapper
- Uses consistent team route structure for the deploy button link
- Follows the established UI component patterns
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx (1)
4-47
: LGTM! Clean and well-structured payment frequency selector.The component effectively uses UI primitives and follows good practices:
- Clear type definitions with
PaymentFrequency
export- Responsive grid layout for different screen sizes
- Proper use of
RadioGroup
with controlled state- Good visual hierarchy with discount badge for annual option
- Consistent styling patterns with data attributes
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx (1)
1-206
: LGTM! Comprehensive and well-structured checkout flow.This is an excellent implementation of a multi-step infrastructure deployment checkout:
Strengths:
- Correct use of
"use client"
directive and React hooks- Well-organized service configuration with clear pricing and features
- Proper state management for chain, services, and payment frequency
- Good responsive design with logical grid layout
- Appropriate use of
ClientOnly
wrapper for client-side components- Clear step-by-step UI with badges and descriptions
- Comprehensive order summary with chain details and fallback states
- Follows established patterns from the codebase
Architecture:
- Clean separation of concerns with imported child components
- Good use of existing UI primitives (Card, Badge, etc.)
- Proper handling of derived state with
useMemo
- RPC service correctly marked as required and pre-selected
apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx (1)
41-136
: LGTM! Well-implemented discriminated union for CTA variants.The update effectively supports both link-based and callback-based CTAs:
Good practices:
- Clean discriminated union type definition using presence of
target
vsonClick
- Proper conditional rendering logic to distinguish between variants
- Correct security attributes (
rel="noopener noreferrer"
) for external links- Consistent styling and icon handling across both variants
- Follows established component patterns in the codebase
The type-safe approach ensures proper usage of each CTA variant while maintaining backward compatibility.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx (1)
156-158
: Add null safety for service access.The code uses optional chaining for
service?.monthlyPrice
but doesn't handle the case whereservice
itself might be null/undefined in the filter.const baseMonthlyTotal = selectedServices.reduce((total, service) => { - return total + (service?.monthlyPrice || 0); + return total + (service?.monthlyPrice ?? 0); - }, 0); + }, 0);Consider filtering out null services before the reduce operation:
const baseMonthlyTotal = selectedServices + .filter(Boolean) + .reduce((total, service) => { - return total + (service?.monthlyPrice || 0); + return total + service.monthlyPrice; }, 0);⛔ Skipped due to learnings
Learnt from: MananTank PR: thirdweb-dev/js#7177 File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_hooks/useTokenPriceData.ts:49-49 Timestamp: 2025-05-27T19:55:25.056Z Learning: In the ERC20 public pages token price data hook (`useTokenPriceData.ts`), direct array access on `json.data[0]` without optional chaining is intentionally correct and should not be changed to use safety checks.
.../src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx
Outdated
Show resolved
Hide resolved
...c/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx
Outdated
Show resolved
Hide resolved
...c/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx
Outdated
Show resolved
Hide resolved
71255ca
to
f9d44a0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (2)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (2)
53-53
: Use ID-based comparison instead of object reference equality.The current implementation uses
includes()
which relies on reference equality. This may fail if service objects are recreated with the same data but different references.- const isSelected = props.selectedServices.includes(service); + const isSelected = props.selectedServices.some(s => s.id === service.id);
84-90
: Remove redundant null check.The
nextServiceToAdd
is already checked to be truthy in the ternary condition on line 82, making the inner null check redundant.onClick: () => { - if (nextServiceToAdd) { props.setSelectedServices([ ...props.selectedServices, nextServiceToAdd, ]); - } },
🧹 Nitpick comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (1)
138-138
: Consider edge case handling for zero pricing.While unlikely in this context, the pricing display doesn't handle edge cases where
monthlyPrice
might be 0. Consider if this scenario needs special handling or messaging.- ${props.service.monthlyPrice.toLocaleString()} + {props.service.monthlyPrice === 0 ? 'Free' : `$${props.service.monthlyPrice.toLocaleString()}`}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
apps/dashboard/biome.json
(1 hunks)apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx
(2 hunks)apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx
(2 hunks)apps/dashboard/src/@/icons/ChainIcon.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx
(1 hunks)apps/nebula/biome.json
(1 hunks)apps/playground-web/biome.json
(1 hunks)apps/portal/biome.json
(1 hunks)apps/wallet-ui/biome.json
(1 hunks)biome.json
(1 hunks)packages/engine/biome.json
(1 hunks)packages/insight/biome.json
(1 hunks)packages/nebula/biome.json
(1 hunks)packages/react-native-adapter/biome.json
(1 hunks)packages/service-utils/biome.json
(1 hunks)packages/thirdweb/biome.json
(1 hunks)packages/vault-sdk/biome.json
(1 hunks)packages/wagmi-adapter/biome.json
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (25)
- apps/dashboard/biome.json
- packages/wagmi-adapter/biome.json
- biome.json
- apps/portal/biome.json
- packages/service-utils/biome.json
- packages/thirdweb/biome.json
- packages/engine/biome.json
- packages/insight/biome.json
- apps/wallet-ui/biome.json
- packages/vault-sdk/biome.json
- packages/nebula/biome.json
- packages/react-native-adapter/biome.json
- apps/nebula/biome.json
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx
- apps/playground-web/biome.json
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx
- apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx
- apps/dashboard/src/@/icons/ChainIcon.tsx
- apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.@(ts|tsx)`: Accept a typed 'props' object and export a named function (e.g...
**/*.@(ts|tsx)
: Accept a typed 'props' object and export a named function (e.g., export function MyComponent()).
Combine class names via 'cn', expose 'className' prop if useful.
Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Local state or effects live inside; data fetching happens in hooks.
Merge class names with 'cn' from '@/lib/utils' to keep conditional logic readable.
Stick to design-tokens: background ('bg-card'), borders ('border-border'), muted text ('text-muted-foreground') etc.
Use the 'container' class with a 'max-w-7xl' cap for page width consistency.
Spacing utilities ('px-', 'py-', 'gap-*') are preferred over custom margins.
Responsive helpers follow mobile-first ('max-sm', 'md', 'lg', 'xl').
Never hard-code colors – always go through Tailwind variables.
Tailwind CSS is the styling system – avoid inline styles or CSS modules.
Prefix files with 'import "server-only";' so they never end up in the client bundle (for server-only code).
📄 Source: CodeRabbit Inference Engine (.cursor/rules/dashboard.mdc)
List of files the instruction was applied to:
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx
🧠 Learnings (2)
📓 Common learnings
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (5)
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Prefer composable UI primitives (Button, Input, Select, Tabs, Card, Sidebar, Separator, Badge) over custom markup for maintainability and design consistency.
🧬 Code Graph Analysis (1)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (1)
apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx (1)
UpsellBannerCard
(57-140)
⏰ Context from checks skipped due to timeout of 90000ms (7)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Size
- GitHub Check: Unit Tests
- GitHub Check: Build Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (3)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (3)
9-20
: Type definitions look well-structured.The
Service
union type andServiceConfig
interface are properly defined and provide good type safety. The interface covers all necessary service metadata including pricing, features, and UI elements.
27-32
: Good use of useMemo for performance optimization.The
nextServiceToAdd
computation correctly uses ID-based comparison and is properly memoized with appropriate dependencies.
106-157
: ServiceCheckboxCard component follows best practices.The component properly:
- Uses semantic HTML with Label for accessibility
- Implements conditional styling with
cn()
utility- Handles required services appropriately by disabling interaction
- Uses design system components (Checkbox, Badge)
- Applies responsive design patterns with
lg:
prefixes
f9d44a0
to
4bd0809
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #7456 +/- ##
=======================================
Coverage 51.96% 51.96%
=======================================
Files 952 952
Lines 64224 64224
Branches 4237 4239 +2
=======================================
Hits 33377 33377
Misses 30740 30740
Partials 107 107
🚀 New features to boost your workflow:
|
4bd0809
to
ae2e3de
Compare
744b7d3
to
2ba67fb
Compare
2ba67fb
to
21a2a3f
Compare
21a2a3f
to
e71e41f
Compare
e71e41f
to
aec866a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx (1)
65-69
: The service availability validation is still missing.The component accepts a
chain
prop of typeChainMetadataWithServices
but doesn't validate whether the selected services are actually available for this specific chain before allowing checkout. This was previously flagged but not yet implemented.
🧹 Nitpick comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx (1)
385-459
: Consider extracting ServiceCard to a separate component file.The
ServiceCard
component is well-implemented but is quite substantial (75 lines). Consider extracting it to a separate file for better maintainability and reusability across the codebase.// Create a new file: service-card.tsx +import { Badge } from "@/components/ui/badge"; +import { cn } from "@/lib/utils"; +import { RPCIcon, InsightIcon, SmartAccountIcon } from "@/icons"; + +export function ServiceCard(props: ServiceCardProps) { + // ... existing ServiceCard implementation +}Then import and use it in the main file:
-// --- Service Card Component --- -type IconKey = "RPCIcon" | "InsightIcon" | "SmartAccountIcon"; -// ... ServiceCard implementation +import { ServiceCard } from "./service-card";
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (55)
apps/dashboard/src/@/actions/billing.ts
(3 hunks)apps/dashboard/src/@/api/ecosystems.ts
(2 hunks)apps/dashboard/src/@/api/team-subscription.ts
(4 hunks)apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx
(2 hunks)apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx
(2 hunks)apps/dashboard/src/@/components/blocks/full-width-sidebar-layout.tsx
(1 hunks)apps/dashboard/src/@/icons/ChainIcon.tsx
(1 hunks)apps/dashboard/src/@/storybook/stubs.ts
(3 hunks)apps/dashboard/src/@/types/billing.ts
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/explore/components/contract-row/index.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/TeamSidebarLayout.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx
(3 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/billing/layout.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/components/EcosystemAnalyticsPage.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/components/EcosystemWalletUsersChartCard.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/EcosystemSlugLayout.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/ecosystem-header.client.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/add-partner/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/AddPartnerDialogButton.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/add-partner-form.client.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/auth-options-form.client.tsx
(3 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/integration-permissions-toggle.client.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/partner-form.client.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/update-partner-form.client.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/auth-options-section.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/ecosystem-partners-section.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/integration-permissions-section.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/partners-table.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/fetchEcosystem.ts
(0 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/fetchPartnerDetails.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/fetchPartners.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-add-partner.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-delete-partner.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-update-ecosystem.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-update-partner.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/partners/[partner_id]/edit/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/hooks/use-ecosystem.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/hooks/use-partners.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/create/actions/create-ecosystem.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/utils/fetchEcosystem.ts
(0 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/utils/fetchEcosystemList.ts
(0 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/_components/service-card.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/[chain_id]/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/search-params.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/usage/layout.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/sales/sales-settings.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/settings/components/index.tsx
(1 hunks)packages/thirdweb/src/react/web/ui/components/Modal.tsx
(7 hunks)
💤 Files with no reviewable changes (3)
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/utils/fetchEcosystem.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/utils/fetchEcosystemList.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/fetchEcosystem.ts
✅ Files skipped from review due to trivial changes (1)
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-update-ecosystem.ts
🚧 Files skipped from review as they are similar to previous changes (50)
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/components/EcosystemAnalyticsPage.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/components/EcosystemWalletUsersChartCard.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/auth-options-section.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/update-partner-form.client.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-update-partner.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/fetchPartners.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/partners-table.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/hooks/use-ecosystem.ts
- apps/dashboard/src/app/(app)/(dashboard)/explore/components/contract-row/index.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/AddPartnerDialogButton.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/add-partner-form.client.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/hooks/use-partners.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-delete-partner.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/integration-permissions-section.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/billing/layout.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/create/actions/create-ecosystem.ts
- apps/dashboard/src/@/icons/ChainIcon.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/usage/layout.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/integration-permissions-toggle.client.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/ecosystem-partners-section.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/sales/sales-settings.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/settings/components/index.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/fetchPartnerDetails.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/partner-form.client.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/search-params.ts
- apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/add-partner/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/page.tsx
- apps/dashboard/src/@/types/billing.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/EcosystemSlugLayout.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/partners/[partner_id]/edit/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-add-partner.ts
- apps/dashboard/src/@/components/blocks/full-width-sidebar-layout.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/ecosystem-header.client.tsx
- apps/dashboard/src/@/storybook/stubs.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/TeamSidebarLayout.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/auth-options-form.client.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx
- apps/dashboard/src/@/actions/billing.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/[chain_id]/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx
- packages/thirdweb/src/react/web/ui/components/Modal.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/_components/service-card.tsx
- apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx
- apps/dashboard/src/@/api/ecosystems.ts
- apps/dashboard/src/@/api/team-subscription.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx
🧰 Additional context used
📓 Path-based instructions (2)
`**/*.{ts,tsx}`: Write idiomatic TypeScript with explicit function declarations ...
**/*.{ts,tsx}
: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/types
or localtypes.ts
barrels
Prefer type aliases over interface except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial
,Pick
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx
`apps/{dashboard,playground-web}/**/*.{tsx,ts}`: Import UI primitives from `@/co...
apps/{dashboard,playground-web}/**/*.{tsx,ts}
: Import UI primitives from@/components/ui/*
(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
UseNavLink
for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()
from@/lib/utils
for conditional class merging
Use design system tokens (e.g.,bg-card
,border-border
,text-muted-foreground
)
ExposeclassName
prop on root element for overrides in UI components
Server Components (Node edge): Start files withimport "server-only";
Server Components: Read cookies/headers withnext/headers
Server Components: Access server-only environment variables
Server Components: Perform heavy data fetching
Server Components: Implement redirect logic withredirect()
fromnext/navigation
Client Components (browser): Begin files with'use client';
Client Components: Handle interactive UI with React hooks (useState
,useEffect
, React Query, wallet hooks)
Client Components: Access browser APIs (localStorage
,window
,IntersectionObserver
)
Client Components: Support fast transitions with prefetched data
Server Side Data Fetching: Always callgetAuthToken()
to retrieve JWT from cookies
Server Side Data Fetching: UseAuthorization: Bearer
header – never embed tokens in URLs
Server Side Data Fetching: Return typed results (Project[]
,User[]
) – avoidany
Client Side Data Fetching: Wrap calls in React Query (@tanstack/react-query
)
Client Side Data Fetching: Use descriptive, stablequeryKeys
for cache hits
Client Side Data Fetching: ConfigurestaleTime
/cacheTime
based on freshness (default ≥ 60s)
Client Side Data Fetching: Keep tokens secret via internal API routes or server actions
Analytics Events: Never importposthog-js
in server components
📄 Source: CodeRabbit Inference Engine (CLAUDE.md)
List of files the instruction was applied to:
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.488Z
Learning: Surface breaking changes prominently in PR descriptions
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx (29)
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/*.client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.489Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{tsx,ts} : Client Components: Handle interactive UI with React hooks (`useState`, `useEffect`, React Query, wallet hooks)
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.488Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{tsx,ts} : Import UI primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/*.client.tsx : Anything that consumes hooks from `@tanstack/react-query` or thirdweb SDKs.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : For notices & skeletons rely on `AnnouncementBanner`, `GenericLoadingPage`, `EmptyStateCard`.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.489Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{tsx,ts} : Client Components: Support fast transitions with prefetched data
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/*.{tsx,client.tsx} : Name files after the component in PascalCase; append `.client.tsx` when interactive.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.489Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{tsx,ts} : Server Components: Perform heavy data fetching
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.489Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{tsx,ts} : Client Components (browser): Begin files with `'use client';`
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: MananTank
PR: thirdweb-dev/js#7177
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_hooks/useTokenTransfers.ts:41-44
Timestamp: 2025-05-27T19:56:16.920Z
Learning: When reviewing hooks that use environment variables like NEXT_PUBLIC_DASHBOARD_THIRDWEB_CLIENT_ID for API calls, MananTank prefers not to add explicit validation checks for these variables, trusting they will be set in the deployment environment.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.488Z
Learning: Applies to **/*.test.{ts,tsx} : Use `FORKED_ETHEREUM_CHAIN` for mainnet interactions and `ANVIL_CHAIN` for isolated tests
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.488Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{tsx,ts} : Use `cn()` from `@/lib/utils` for conditional class merging
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.488Z
Learning: Applies to **/*.{ts,tsx} : Comment only ambiguous logic; avoid restating TypeScript in prose
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: jnsdls
PR: thirdweb-dev/js#7364
File: apps/dashboard/src/app/(app)/account/components/AccountHeader.tsx:36-41
Timestamp: 2025-06-18T02:13:34.500Z
Learning: In the logout flow in apps/dashboard/src/app/(app)/account/components/AccountHeader.tsx, when `doLogout()` fails, the cleanup steps (resetAnalytics(), wallet disconnect, router refresh) should NOT execute. This is intentional to maintain consistency - if server-side logout fails, client-side cleanup should not occur.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/pages/*.client.tsx : Pages requiring fast transitions where data is prefetched on the client.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/shared-claim-conditions-page.tsx:43-49
Timestamp: 2025-05-26T16:31:02.480Z
Learning: In the thirdweb dashboard codebase, when `redirectToContractLandingPage()` is called, an explicit return statement is not required afterward because the function internally calls Next.js's `redirect()` which throws an error to halt execution.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Local state or effects live inside; data fetching happens in hooks.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Always import from the central UI library under `@/components/ui/*` – e.g. `import { Button } from "@/components/ui/button"`.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Prefer composable primitives over custom markup: `Button`, `Input`, `Select`, `Tabs`, `Card`, `Sidebar`, `Separator`, `Badge`.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Icons come from `lucide-react` or the project-specific `…/icons` exports – never embed raw SVG.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Use `NavLink` (`@/components/ui/NavLink`) for internal navigation so active states are handled automatically.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Stick to design-tokens: background (`bg-card`), borders (`border-border`), muted text (`text-muted-foreground`) etc.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/*.client.tsx : Client components must start with `'use client';` before imports.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Place the file close to its feature: `feature/components/MyComponent.tsx`.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/index.ts : Group related components in their own folder and expose a single barrel `index.ts` where necessary.
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: Unit Tests
- GitHub Check: Lint Packages
- GitHub Check: Build Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx (2)
19-61
: LGTM: Well-structured service configuration.The service configuration object is well-designed with proper TypeScript constraints using
satisfies
. The pricing structure is clear and the type safety ensures consistency across the codebase.
175-203
: LGTM: Checkout function properly implemented.The checkout function now correctly uses
startTransition
to wrap the async operation and includes proper error handling with user feedback via toast notifications.
Add Infrastructure Section to Team Dashboard
This PR adds a new "Infrastructure" section to the team dashboard, allowing users to deploy and manage blockchain infrastructure services. Key changes include:
UpsellBannerCard
component to support onClick handlersdisableDeprecated
option toSingleNetworkSelector
componentThe infrastructure deployment UI includes detailed pricing information, bundle discounts, and a complete checkout experience for teams to easily deploy blockchain infrastructure services.
Summary by CodeRabbit
New Features
Enhancements
Bug Fixes
Refactor
Chores
PR-Codex overview
This PR focuses on refactoring and updating the ecosystem management codebase, enhancing type definitions, consolidating utility functions, and improving component imports for better organization and maintainability.
Detailed summary
fetchEcosystem.ts
andfetchEcosystemList.ts
.ChainInfraSKU
type for billing.Ecosystem
andPartner
across multiple files.fetchEcosystem
andfetchEcosystemList
functions to streamline API calls.